package com.kotlinvben.service

import com.kotlinvben.entity.Department
import com.kotlinvben.exception.DepartmentCircularReferenceException
import com.kotlinvben.exception.DepartmentNameExistsException
import com.kotlinvben.exception.DepartmentNotFoundException
import com.kotlinvben.exception.DepartmentParentNotFoundException
import com.kotlinvben.repository.DepartmentRepository
import com.kotlinvben.utils.SecurityUtils
import com.kotlinvben.vo.DepartmentUpdateVO
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional
class DepartmentService(
    private val departmentRepository: DepartmentRepository
) {
    fun getDepartmentById(id: Long): Department? {
        return departmentRepository.findById(id).orElse(null)
    }

    fun getDepartments(): List<Department> {
        // 1. 查询所有根部门（pid为null）
        val rootDepartments = departmentRepository.findByPidIsNull()
            .sortedBy { it.sort }
        
        // 2. 递归查询每个根部门的子部门
        rootDepartments.forEach { root ->
            findChildren(root)
        }
        
        return rootDepartments
    }

    private fun findChildren(department: Department) {
        // 1. 查询当前部门的子部门
        val children = departmentRepository.findByPid(department.id!!)
            .sortedBy { it.sort }
        
        // 2. 将子部门添加到当前部门
        department.children = children.toMutableList()
        
        // 3. 递归查询每个子部门的子部门
        children.forEach { child ->
            findChildren(child)
        }
    }

    fun createDepartment(department: Department): Department {
        // 检查部门名称是否已存在
        if (departmentRepository.existsByName(department.name!!)) {
            throw DepartmentNameExistsException(department.name!!)
        }

        // 检查父部门是否存在
        department.pid?.let { parentId ->
            if (!departmentRepository.existsById(parentId)) {
                throw DepartmentParentNotFoundException(parentId)
            }
        }

        // 如果 pid 为 null，设置为 0
        if (department.pid == null) {
            department.pid = 0L
        }

        return departmentRepository.save(department)
    }

    fun updateDepartment(id: Long, updateVO: DepartmentUpdateVO): Department {
        val department = getDepartmentById(id) ?: throw DepartmentNotFoundException(id)

        // 检查部门名称是否已存在（排除自身）
        if (departmentRepository.existsByName(updateVO.name) && department.name != updateVO.name) {
            throw DepartmentNameExistsException(updateVO.name)
        }

        // 检查父部门是否存在
        updateVO.pid?.let { parentId ->
            if (!departmentRepository.existsById(parentId)) {
                throw DepartmentParentNotFoundException(parentId)
            }
            // 检查是否形成循环引用
            if (parentId == id) {
                throw DepartmentCircularReferenceException(id, parentId)
            }
        }

        department.name = updateVO.name
        department.remarks = updateVO.remarks
        department.pid = updateVO.pid
        department.sort = updateVO.sort
        department.status = updateVO.status
        department.modifyBy = SecurityUtils.getCurrentUsername()
        return departmentRepository.save(department)
    }

    fun deleteDepartment(id: Long) {
        if (!departmentRepository.existsById(id)) {
            throw DepartmentNotFoundException(id)
        }
        departmentRepository.deleteById(id)
    }
} 